package com.playground.movearound;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;
import android.view.View;

public class MoveAroundView extends View {

	private static int MIN_SIZE;
	private static int MAX_SIZE;
	private static int WIDTH;
	private static int HEIGHT;
	private static int BASE;
	
	private ScaleGestureDetector gesture;
	private Paint paint;
	private Rect bounds;
	private Drawable rect;
	private boolean inDrag;
	private boolean needCenter;
	
	public MoveAroundView(Context context) {
		super(context);
	
		setFocusableInTouchMode(true);
		gesture = new ScaleGestureDetector(context, new ScaleListener());
		
		inDrag = false;
		needCenter = false;
		bounds = new Rect();
		
		rect = context.getResources().getDrawable(R.drawable.rect);
		rect.setBounds(bounds);
		
		paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint.setColor(0xffe5b154);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
		int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
		int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
		
		int shortest = Math.min(parentWidth, parentHeight);
		
		MAX_SIZE = shortest / 2;
		MIN_SIZE = shortest / 10;
		WIDTH = HEIGHT = MIN_SIZE * 2;
		BASE = MIN_SIZE * 2 / 3;
		bounds.set(BASE, BASE, BASE+WIDTH, BASE+HEIGHT);
		rect.setBounds(bounds);
		
		this.setMeasuredDimension(parentWidth , parentHeight);
	}
	
	protected void onDraw(Canvas canvas) {
		if ( needCenter ) {
			needCenter = false;
			centerAt(bounds.centerX(), bounds.centerY());
		}
		canvas.drawColor(0xff3593f1);
		rect.draw(canvas);
	}
	
	public void onOrientationChanged(int newOrientation) {
		needCenter = true;
	}
	
	private void centerAt(int x, int y) {
		int w = bounds.width();
		int h = bounds.height();
		if ( x - w / 2 < 0 ) {
			x = w / 2;
		} else if ( x + w / 2 >= getWidth() ) {
			x = getWidth() - w / 2;
		}
		if ( y - h / 2 < 0 ) {
			y = h / 2;
		} else if ( y + h / 2 >= getHeight() ) {
			y = getHeight() - h / 2;
		}
		bounds.offset(x - bounds.centerX(), y - bounds.centerY());
		rect.setBounds(bounds);
		invalidate();
	}
	
	private void doScale(float factor) {
		
		int w = bounds.width();
		int size = (int) (w * factor);
		if      ( size < MIN_SIZE )	size = MIN_SIZE;
		else if ( size > MAX_SIZE ) size = MAX_SIZE;
	
		int diff = w - size;
		
		bounds.inset(diff, diff);
		
		centerAt(bounds.centerX(), bounds.centerY());
	}
	
	public boolean onTouchEvent (MotionEvent event) {
		
		gesture.onTouchEvent(event);
		
		float x = event.getX();
		float y = event.getY();
		
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if ( bounds.contains((int) x, (int) y) ) {
				inDrag = true;
				centerAt((int) x, (int) y);
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if ( inDrag ) {
				centerAt((int) x, (int) y);
			}
			break;
		case MotionEvent.ACTION_UP:
			inDrag = false;
			break;
		default:
		}
		return true;
	}
	
	private class ScaleListener extends SimpleOnScaleGestureListener {
		
		public boolean onScaleBegin(ScaleGestureDetector detector) {
			int focusX = (int) detector.getFocusX();
			int focusY = (int) detector.getFocusY();
			return bounds.contains(focusX, focusY);
		}
		
		public boolean onScale(ScaleGestureDetector detector) {
			
			float previous = detector.getPreviousSpan();
			float current = detector.getCurrentSpan();
			float factor = detector.getScaleFactor();
			float diff = current - previous;
			
			if ( Math.abs(diff) < 0.01 )
				return false;
			
			doScale(factor);
			return true;
		}
		
	}
	
}
